package me.chyxion.spring.ext;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;

/**
 * @version 0.0.1
 * @since 0.0.1
 * @author Shaun Chyxion <br />
 * xiaoning.chen@flaginfo.com.cn <br />
 * Jan 16, 2015 5:33:30 PM
 */
public class ResourceModel {
	private static final Logger log = LoggerFactory.getLogger(ResourceModel.class);

	private String contentType;
	private String name;
	private Resource resource;

	/**
	 * @param name
	 * @param resource
	 */
	public ResourceModel(String name, Resource resource) {
		this(resource);
		if (StringUtils.isNotBlank(name)) {
			this.name = name;
		}
	}

	public ResourceModel(Resource resource) {
		this.resource = resource;
		name = resource.getFilename();
	}

	public ResourceModel(File file) {
		this.name = file.getName();
		this.resource = new FileSystemResource(file);
	}
	
	public ResourceModel(String name, InputStream inputStream) {
		this(inputStream);
		this.name = name;
	}

	public ResourceModel(InputStream inputStream) {
		this.resource = new InputStreamResource(inputStream);
	}

	public ResourceModel(String name, byte[] data) {
		this(data);
		this.name = name;
	}

	public ResourceModel(byte[] data) {
		this.resource = new ByteArrayResource(data);
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}
	/**
	 * @param name the name to set
	 * @return 
	 */
	public ResourceModel setName(String name) {
		this.name = name;
		return this;
	}
	/**
	 * @return the resource
	 */
	public Resource getResource() {
		return resource;
	}
	/**
	 * @param resource the resource to set
	 * @return 
	 */
	public ResourceModel setResource(Resource resource) {
		this.resource = resource;
		return this;
	}

	/**
	 * @return the contentType
	 */
	public String getContentType() {
		if (StringUtils.isBlank(contentType)) {
			// from file name
			if (StringUtils.isNotBlank(name)) {
				contentType = URLConnection.guessContentTypeFromName(name);
			}
			// from input stream
			else {
				InputStream stream = null;
				try {
					stream = new BufferedInputStream(resource.getInputStream());
					contentType = URLConnection.guessContentTypeFromStream(stream);
				}
				catch (IOException e) {
					log.warn("Get Resouce Input Stream Content Type Error Caused.", e);
				}
				finally {
					IOUtils.closeQuietly(stream);
				}
			}
			// use default
			if (StringUtils.isBlank(contentType)) {
				contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
			}
		}
		return contentType;
	}

	/**
	 * @param contentType the contentType to set
	 * @return 
	 */
	public ResourceModel setContentType(String contentType) {
		this.contentType = contentType;
		return this;
	}
}
